module uart_tfifo (clk, 
	rst_n, data_in, data_out,
// Control signals
	wen, // wen strobe, active high
	ren,   // ren strobe, active high
// status signals
	overrun,
	count,
	fifo_reset,
	reset_status,
   full,empty
	);


// FIFO parameters
parameter fifo_width = 8;
parameter fifo_depth = 16;
parameter fifo_pointer_w = 4;
parameter fifo_counter_w = 5;

input				clk;
input				rst_n;
input				wen;
input				ren;
input	[fifo_width-1:0]	data_in;
input				fifo_reset;
input       reset_status;

output	[fifo_width-1:0]	data_out;
output				overrun;
output	[fifo_counter_w-1:0]	count;
output reg   full,empty;

wire	[fifo_width-1:0]	data_out;

// FIFO pointers
reg	[fifo_pointer_w-1:0]	top;
reg	[fifo_pointer_w-1:0]	bottom;

reg	[fifo_counter_w-1:0]	count;
reg				overrun;
wire [fifo_pointer_w-1:0] top_plus_1 = top + 1'b1;
reg    [fifo_width-1:0] mem [fifo_depth-1:0]; 


always @(posedge clk) begin   
    if (wen)   
      mem[top] <= data_in;   
end   

assign data_out = mem[bottom];   



always @(posedge clk or negedge rst_n) begin// synchronous FIFO
	if (!rst_n) begin
		top		<=  0;
		bottom	<=  1'b0;
		count		<=  0;
	end
	else if (fifo_reset) begin
		top		<=  0;
		bottom   <=  1'b0;
		count		<=  0;
	end
   else begin
		case ({wen, ren})
		   2'b10 : if (count<fifo_depth)  // overrun condition
		   	begin
		   		top       <=  top_plus_1;
		   		count     <=  count + 1'b1;
		   	end
		   2'b01 : if(count>0)
		   	begin
		   		bottom   <=  bottom + 1'b1;
		   		count	 <=  count - 1'b1;
		   	end
		   2'b11 : begin
		   		bottom   <=  bottom + 1'b1;
		   		top       <=  top_plus_1;
		           end
         default: ;
		endcase
	end
end   // always

always @(posedge clk or negedge rst_n) // synchronous FIFO
begin
  if (!rst_n)
    overrun   <=  1'b0;
  else
  if(fifo_reset | reset_status) 
    overrun   <=  1'b0;
  else
  if(wen & (count==fifo_depth))
    overrun   <=  1'b1;
end   // always

always @ ( posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        full <= 0;
        empty <= 1;
    end
    else if (fifo_reset) begin
        full <= 0;
        empty <= 1;
    end
    else begin
        if((count == fifo_depth) & ~wen & ren)
            full <= 0;
        else if(((count == (fifo_depth-1)) & wen & ~ren))
            full <= 1;

        if (!wen & ren &  (count==1))    empty <= 1;
        else if(wen  & !ren &  empty)    empty <= 0;
    end
end
    //}}}

endmodule
